#ifndef HAND_H_
#define HAND_H_

#include "Card.h"

namespace core
{

#define BOX1_NUM_OF_CARDS 3
#define BOX2_NUM_OF_CARDS 5
#define BOX3_NUM_OF_CARDS 5
#define NUM_OF_CARDS_IN_HAND 13

#define NUM_OF_BOXES_IN_HAND 3

#define STRONG_COMBINATIONS_MIN_CARDS 4


class Box
{
public:
	Box(Card* first_card_ptr, int box_size);

	inline Card* beg() const { return mFront; }
	inline Card* back() const { return mBack; }
	inline Card* curr() const { return mIter; }
	
	inline bool full() const { return mCardsRest == 0; }
	inline bool empty() const { return curr() == beg(); }

	void clear();
	
	int insert(Card c);

	friend std::ostream& operator<< (std::ostream &output, Box obj);

	uint8 power();

private:
	uint8 count_ready_cards() const;

	uint8 is_straight_flush();
	uint8 is_quads();
	uint8 is_full_house();
	uint8 is_flush();
	uint8 is_straight();
	uint8 is_set();
	uint8 is_pairs();

	uint8 max_rank();
	uint8 min_rank();
	uint8 count_rank(uint8 rnk);

private:
	Card* mFront;
	Card* mBack;
	Card* mIter;

	uint8 mCardsRest;
};




class Hand
{
public:
	Hand();
	
	inline bool full() const { return (mCardsCount == NUM_OF_CARDS_IN_HAND); }
	int insert(Card c, uint8 box_num);

	inline uint8 count() const { return mCardsCount; }
	uint8 l_count() const;

	friend std::ostream& operator<< (std::ostream &output, Hand obj);

	bool valid() const;
	void powers_count();

	inline uint8 box_power(uint8 box_num) const { return mPower[box_num]; }

protected:
	Card mCards[NUM_OF_CARDS_IN_HAND];
	Box mBox1;
	Box mBox2;
	Box mBox3;

	Box* mBoxes[NUM_OF_BOXES_IN_HAND];
	uint8 mPower[NUM_OF_BOXES_IN_HAND];

	uint8 mCardsCount;


};

} // namespace core

#endif // HAND_H_